<template>
    <el-dialog v-model="isOpen" title="计算结果" width="800px" :border="true" align-center>

        <div class="heatmapContainer">
            <div ref="mapRef" class="map-wrapper" />
        </div>

        <!-- 热力图控制滑块 -->
        <div class="heatmap-controls">
            <div class="control-item">
                <label>半径: {{ radius }}px</label>
                <el-slider v-model="radius" :min="5" :max="50" :step="1" @change="updateHeatmap" />
            </div>
            <div class="control-item">
                <label>模糊: {{ blur }}px</label>
                <el-slider v-model="blur" :min="1" :max="30" :step="1" @change="updateHeatmap" />
            </div>
        </div>

    </el-dialog>
</template>

<script setup>
import { nextTick, onMounted, onUnmounted, ref, watch } from "vue"
import Map                                              from "ol/Map"
import View                                             from "ol/View"
import TileLayer                                        from "ol/layer/Tile"
import XYZ                                              from "ol/source/XYZ"
import VectorSource                                     from "ol/source/Vector"
import HeatmapLayer                                     from "ol/layer/Heatmap"
import { fromLonLat }                                   from "ol/proj"
import { Feature }                                      from "ol"
import { Point }                                        from "ol/geom"
import { getCenter }                                    from "ol/extent"

let isOpen = defineModel()
let props  = defineProps([ "resultData" ])

// 热力图控制参数（与官网示例对应）
let radius = ref(15)  // 初始半径
let blur   = ref(30)    // 初始模糊度

// 地图实例和容器引用
let mapRef       = ref(null)
let map          = null
let baseLayer    = null
let heatmapLayer = null
let vectorSource = null

// 销毁现有地图
function destroyMap(){
    if(map){
        if(baseLayer){
            map.removeLayer(baseLayer)
        }
        if(heatmapLayer){
            map.removeLayer(heatmapLayer)
        }
        map.setTarget(null)
        map          = null
        baseLayer    = null
        heatmapLayer = null
        vectorSource = null
    }
}

// 更新热力图参数
function updateHeatmap(){
    if(heatmapLayer){
        heatmapLayer.setBlur(blur.value)
        heatmapLayer.setRadius(radius.value)
    }
}

// 初始化热力图
function initHeatmap(){
    nextTick(() => {
        if(!mapRef.value || !props.resultData || !props.resultData.heatmapOpenlayers?.length){
            return
        }

        destroyMap()

        // 创建基础图层
        baseLayer = new TileLayer({
            source: new XYZ({
                url: "https://webrd0{1-4}.is.autonavi.com/appmaptile?style=7&x={x}&y={y}&z={z}&lang=zh_cn&size=1&scale=1",
            }),
        })

        // 准备热力图数据
        const features         = []
        const heatmapData      = props.resultData.heatmapOpenlayers
        const densities        = heatmapData.map(item => item.density)
        const min              = Math.min(...densities)
        const max              = Math.max(...densities)
        const validCoordinates = []

        heatmapData.forEach(item => {
            const lon = parseFloat(item.centerLon)
            const lat = parseFloat(item.centerLat)

            if(isNaN(lon) || isNaN(lat)){
                console.warn("无效的坐标值:", item)
                return
            }

            const coordinates = fromLonLat([ lon, lat ])
            validCoordinates.push(coordinates)

            // 创建要素（存储密度值用于热力图权重）
            const feature = new Feature({
                geometry: new Point(coordinates),
                weight  : item.density,  // 权重值，用于热力图强度
            })
            features.push(feature)
        })

        // 创建矢量数据源
        vectorSource = new VectorSource({
            features: features,
        })

        // 创建官方热力图图层（使用官网示例的颜色方案）
        heatmapLayer = new HeatmapLayer({
            source: vectorSource,
            blur  : blur.value,
            radius: radius.value,
            weight: function(feature){
                // 归一化权重值
                const value = feature.get("weight") || 0
                return max > min ? (value - min) / (max - min) : 0.5
            },
            // 官网示例的绿色到红色渐变
            gradient: [
                "rgba(0, 255, 0, 0)",    // 透明
                "rgba(0, 255, 0, 0.3)",  // 浅绿色
                "rgba(255, 255, 0, 0.6)",// 黄色
                "rgba(255, 165, 0, 0.8)",// 橙色
                "rgba(255, 0, 0, 1)",     // 红色
            ],
        })

        // 创建地图实例
        map = new Map({
            target  : mapRef.value,
            layers  : [ baseLayer, heatmapLayer ],
            view    : new View({
                center : fromLonLat([ 104.114129, 35.675387 ]),
                zoom   : 5,
                maxZoom: 18,
            }),
            controls: [],
        })

        // 适配视野
        if(validCoordinates.length > 0){
            const extent = vectorSource.getExtent()
            const center = getCenter(extent)

            map.getView().setCenter(center)
            setTimeout(() => {
                map.getView().fit(extent, {
                    padding : [ 50, 50, 50, 50 ],
                    maxZoom : 15,
                    duration: 500,
                })
            }, 100)
        }
    })
}

onMounted(() => {
    initHeatmap()
})

// 监听数据变化
watch(() => props.resultData, () => {
    initHeatmap()
}, { deep: true })

// 监听对话框显示状态
watch(isOpen, (newVal) => {
    if(newVal && map){
        map.updateSize()
        if(heatmapLayer){
            const extent = heatmapLayer.getSource().getExtent()
            if(extent){
                map.getView().fit(extent, { padding: [ 50, 50, 50, 50 ] })
            }
        }
    }
})

onUnmounted(() => {
    destroyMap()
})
</script>

<style scoped>
.heatmapContainer {
    width: 100%;
    height: 600px;

    .map-wrapper {
        width: 100%;
        height: 100%;
    }
}

/* 控制滑块样式 */
.heatmap-controls {
    display: flex;
    gap: 30px;

    .control-item {
        display: flex;
        justify-content: center;
        align-items: center;
        width: 200px;

        label {
            display: block;
            color: #666;
            margin-right: 20px;
            width: 80px;
        }

        .el-slider {
            width: 100px;
        }
    }
}

</style>
